﻿using nRFToolbox.Common;
using nRFToolbox.UI;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace nRFToolbox
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
	public sealed partial class App : Application
	{
#if WINDOWS_PHONE_APP
		private TransitionCollection transitions;
		ContinuationManager continuationManager;
#endif

		/// <summary>
		/// Initializes the singleton application object.  This is the first line of authored code
		/// executed, and as such is the logical equivalent of main() or WinMain().
		/// </summary>
		public App()
		{
			this.InitializeComponent();
			this.Suspending += this.OnSuspending;
		}

		private Frame CreateRootFrame()
		{
			Frame rootFrame = Window.Current.Content as Frame;

			// Do not repeat app initialization when the Window already has content,
			// just ensure that the window is active
			if (rootFrame == null)
			{
				// Create a Frame to act as the navigation context and navigate to the first page
				rootFrame = new Frame();

				// Set the default language
				rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];
				rootFrame.NavigationFailed += OnNavigationFailed;

				// Place the frame in the current Window
				Window.Current.Content = rootFrame;
			}

			return rootFrame;
		}

		/// <summary>
		/// Invoked when Navigation to a certain page fails
		/// </summary>
		/// <param name="sender">The Frame which failed navigation</param>
		/// <param name="e">Details about the navigation failure</param>
		void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
		{
			throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
		}

		/// <summary>
		/// Invoked when the application is launched normally by the end user.  Other entry points
		/// will be used when the application is launched to open a specific file, to display
		/// search results, and so forth.
		/// </summary>
		/// <param name="e">Details about the launch request and process.</param>
		protected async override void OnLaunched(LaunchActivatedEventArgs e)
		{
#if DEBUG
			if (System.Diagnostics.Debugger.IsAttached)
			{
				this.DebugSettings.EnableFrameRateCounter = true;
			}
#endif
			Frame rootFrame = CreateRootFrame();
			await RestoreStatusAsync(e.PreviousExecutionState);

			if (rootFrame.Content == null)
			{
#if WINDOWS_PHONE_APP
				// Removes the turnstile navigation for startup.
				if (rootFrame.ContentTransitions != null)
				{
					this.transitions = new TransitionCollection();
					foreach (var c in rootFrame.ContentTransitions)
					{
						this.transitions.Add(c);
					}
				}

				rootFrame.ContentTransitions = null;
				rootFrame.Navigated += this.RootFrame_FirstNavigated;

				//await RegisterUartVoiceCommand();
				// When the navigation stack isn't restored navigate to the first page,
				// configuring the new page by passing required information as a navigation
				// parameter
				if (!rootFrame.Navigate(typeof(MainPage), e.Arguments))
				{
					throw new Exception("Failed to create initial page");
				}
#endif


			}

			// Ensure the current window is active
			Window.Current.Activate();
		}

		private async Task RestoreStatusAsync(ApplicationExecutionState previousExecutionState)
		{
			// Do not repeat app initialization when the Window already has content,
			// just ensure that the window is active
			if (previousExecutionState == ApplicationExecutionState.Terminated)
			{
				// Restore the saved session state only when appropriate
				try
				{
					await SuspensionManager.RestoreAsync();
				}
				catch (SuspensionManagerException)
				{
					//Something went wrong restoring state.
					//Assume there is no state and continue
				}
			}
		}

#if WINDOWS_PHONE_APP
		/// <summary>
		/// Restores the content transitions after the app has launched.
		/// </summary>
		/// <param name="sender">The object where the handler is attached.</param>
		/// <param name="e">Details about the navigation event.</param>
		private void RootFrame_FirstNavigated(object sender, NavigationEventArgs e)
		{
			var rootFrame = sender as Frame;
			rootFrame.ContentTransitions = this.transitions ?? new TransitionCollection() { new NavigationThemeTransition() };
			rootFrame.Navigated -= this.RootFrame_FirstNavigated;
		}
#endif

#if WINDOWS_PHONE_APP
		/// <summary>
		/// Handle OnActivated event to deal with File Open/Save continuation activation kinds
		/// </summary>
		/// <param name="e">Application activated event arguments, it can be casted to proper sub-type based on ActivationKind</param>
		protected async override void OnActivated(IActivatedEventArgs e)
		{
			base.OnActivated(e);

			continuationManager = new ContinuationManager();

			Frame rootFrame = CreateRootFrame();
			await RestoreStatusAsync(e.PreviousExecutionState);

			if (rootFrame.Content == null)
			{
				rootFrame.Navigate(typeof(MainPage));
			}
			
			if(e.Kind == ActivationKind.VoiceCommand)
			{
				//if (!((Frame)Window.Current.Content).Navigate(typeof(NordicUART), "Nordic Uart"))
				//{	
				//}
				VoiceControlHandler.HandleCommand(e, rootFrame);
			}

			var continuationEventArgs = e as IContinuationActivatedEventArgs;
			if (continuationEventArgs != null)
			{
				continuationManager.Continue(continuationEventArgs, rootFrame);
			}
			Window.Current.Activate();
		}
#endif

#if WINDOWS_PHONE_APP
		/// <summary>
		/// Register Cortana voice control, when app is activated/launched
		/// </summary>
		private async Task RegisterUartVoiceCommand()
		{
			var storageFile = await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///UartVoiceCommand.xml"));
			await Windows.Media.SpeechRecognition.VoiceCommandManager.InstallCommandSetsFromStorageFileAsync(storageFile);
		}
#endif

		/// <summary>
		/// Invoked when application execution is being suspended.  Application state is saved
		/// without knowing whether the application will be terminated or resumed with the contents
		/// of memory still intact.
		/// </summary>
		/// <param name="sender">The source of the suspend request.</param>
		/// <param name="e">Details about the suspend request.</param>
		private void OnSuspending(object sender, SuspendingEventArgs e)
		{
			var deferral = e.SuspendingOperation.GetDeferral();

			// TODO: Save application state and stop any background activity
			deferral.Complete();
		}
	}
}
